﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.DirectShow;

namespace Demo
{
    public partial class GraphViewer : UserControl
    {
        public GraphViewer()
        {
            InitializeComponent();
        }

        private FilterGraph graph;

        public void SetGraph(FilterGraph graph, params Uri[] sources)
        {
            this.graph = graph;
            graph.MediaEvent += new EventHandler<MediaEventArgs>(graph_MediaEvent);

            sourceGrid.RowDefinitions[0].Height = new GridLength();
            sourceGrid.RowDefinitions[1].Height = new GridLength();

            bool mustLoad = false;

            // Handle source event
            foreach (var s in GetFiltersByInterface<IUriSourceFilter>())
            {
                mustLoad = true;
                s.LoadCompleted += new System.ComponentModel.AsyncCompletedEventHandler(uriSource_LoadCompleted);
                sourcePanel.Visibility = Visibility.Visible;
                sourceGrid.RowDefinitions[0].Height = new GridLength(1, GridUnitType.Star);
            }
            foreach (var s in GetFiltersByInterface<IStreamSourceFilter>().Where(t => !(t is IUriSourceFilter)))
            {
                s.LoadCompleted += new System.ComponentModel.AsyncCompletedEventHandler(uriSource_LoadCompleted);
                sourcePanel.Visibility = Visibility.Visible;
                sourceGrid.RowDefinitions[1].Height = new GridLength(1, GridUnitType.Star);
            }

            if (mustLoad)
            {
                controlPanel.Visibility = Visibility.Collapsed;
                waitPanel.Visibility = Visibility.Collapsed;
            }
            else
            {
                controlPanel.Visibility = Visibility.Visible;
                waitPanel.Visibility = Visibility.Collapsed;
            }

            foreach (var f in GetFiltersByInterface<IUIElement>())
            {
                UIElement element = f.UIElement;
                mediaContainer.Children.Add(element);
            }

            samples.ItemsSource = sources;
        }

        private IEnumerable<T> GetFiltersByInterface<T>()
        {
            return ((IEnumerable<IBaseFilter>)graph.Filters).Where(f => f is T).Cast<T>();
        }

        void uriSource_LoadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                this.graph.StopAsync();

                ChildWindow errorWin = new ErrorWindow(e.Error);
                errorWin.Show();
            }
            else
            {
                controlPanel.Visibility = Visibility.Visible;
                waitPanel.Visibility = Visibility.Collapsed;
            }
        }

        void graph_MediaEvent(object sender, MediaEventArgs e)
        {
            switch (e.Notification)
            {
                case MediaNotification.Error:
                    this.graph.StopAsync();

                    Exception ex = ((ErrorEventArgs)e).Error;
                    if (ex is DirectShowException && ex.InnerException != null)
                        ex = ex.InnerException;
                    ChildWindow errorWin = new ErrorWindow(ex);
                    errorWin.Show();
                    break;

                case MediaNotification.Completed:
                    this.graph.StopAsync();
                    break;

                case MediaNotification.Stopped:
                    bool found = false;
                    foreach (IFileSinkFilter s in GetFiltersByInterface<IFileSinkFilter>())
                    {
                        if (s.FileStream != null)
                            s.FileStream.Dispose();
                        found = true;
                    }
                    if (found)
                        MessageBox.Show("Write operation done");
                    break;
            }
        }

        private void Play_Click(object sender, RoutedEventArgs e)
        {
            var list = GetFiltersByInterface<IFileSinkFilter>().ToList();
            if (list.Count > 0)
            {
                SaveFileDialog file = new SaveFileDialog();
                if (file.ShowDialog().GetValueOrDefault())
                {
                    foreach (IFileSinkFilter s in list)
                        s.FileStream = file.OpenFile();
                }
                else
                    return;
            }

            graph.RunAsync();
        }

        private void Pause_Click(object sender, RoutedEventArgs e)
        {
            graph.PauseAsync();
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            graph.StopAsync();
        }

        private void Browse_Click(object sender, RoutedEventArgs e)
        {
            localSource.IsChecked = true;

            OpenFileDialog o = new OpenFileDialog();
            if (o.ShowDialog().GetValueOrDefault())
            {
                graph.StopAsync();
                System.Threading.Thread.Sleep(500);

                foreach (var i in GetFiltersByInterface<IStreamSourceFilter>())
                    i.LoadAsync(o.File.OpenRead());
            }
        }

        private void samples_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            sampleSource.IsChecked = true;
            graph.StopAsync();

            System.Threading.Thread.Sleep(500);

            controlPanel.Visibility = Visibility.Collapsed;
            waitPanel.Visibility = Visibility.Visible;

            foreach (var i in GetFiltersByInterface<IUriSourceFilter>())
                i.LoadAsync((Uri)samples.SelectedItem);
        }


    }
}
